package com.ys.service.finance.impl;

import java.math.BigDecimal;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.ys.entity.business.TbBaseInfo;
import com.ys.entity.finance.*;
import com.ys.entity.sys.*;
import com.ys.enume.base.TransactionTypeEnum;
import com.ys.enume.finance.TcwPaymentReturnEnum;
import com.ys.mapper.finance.*;
import com.ys.mapper.finance.TcwOperateFrozenRunningMapper;
import com.ys.service.business.TcwAccountDetailedForCompanyService;
import com.ys.service.finance.TcwFinancialTransactionFlowService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.ys.config.MenuId;
import com.ys.dto.AddDto;
import com.ys.entity.flow.YspModel;
import com.ys.entity.hr.ThrOperateCompanyBankInfo;
import com.ys.enume.finance.TcwOperateFrozenRunningEnum;
import com.ys.enume.flow.FlowEnum;
import com.ys.enume.flow.YsProcInstEnum;
import com.ys.mapper.business.DiySqlMapper;
import com.ys.service.finance.TcwPaymentReturnService;
import com.ys.service.flow.YspTaskService;
import com.ys.util.CheckUtil;
import com.ys.util.shiro.ShiroUtils;
import com.ys.vo.Flow;
import com.ys.vo.R;

@Service("TcwPaymentReturnService")
public class TcwPaymentReturnServiceImpl implements TcwPaymentReturnService {
    private static final Logger logger = LoggerFactory.getLogger(TcwPaymentReturnServiceImpl.class);

    @Autowired
    private TcwPaymentReturnMapper tcwPaymentReturnMapper;

    @Autowired
    private TcwPaymentReturnItemMapper tcwPaymentReturnItemMapper;

    @Autowired
    private YspTaskService yspTaskService;

    @Autowired
    private CheckUtil checkUtil;

    @Autowired
    private DiySqlMapper diySqlMapper;

    @Autowired
    private TcwAccountCountForCompanyMapper tcwAccountCountForCompanyMapper;

    @Autowired
    private TcwOperateFrozenRunningMapper tcwOperateFrozenRunningMapper;

    @Autowired
    private TcwOperateCompanyPrepaymentMapper tcwOperateCompanyPrepaymentMapper;

    @Autowired
    private TcwAccountDetailedForCompanyService tcwAccountDetailedForCompanyService;

    @Autowired
    private TcwFinancialTransactionFlowService tcwFinancialTransactionFlowService;



    /**
     * 新增预付款退回申请
     * @param params
     * @param subData
     * @return
     * @throws Exception
     */
    @Override
    @Transactional(timeout=120,propagation= Propagation.REQUIRES_NEW)
    public R add(Map<String, Object> params, String subData) throws Exception {
        //验证
        String msg = yzMsg(params);
        if (msg != null){
            return R.error(msg);
        }
        TcwPaymentReturn tcwPaymentReturn = JSON.parseObject(JSON.toJSONString(params), TcwPaymentReturn.class);
        if (new TcwPaymentReturn().setBid(tcwPaymentReturn.getBid()).count() != 0){
            return R.error("该单号已存在，核实后再操作!");
        }
        // 验证是否有详情数据
        JSONArray detailJA = JSON.parseArray(subData);
        if (detailJA == null || detailJA.size() == 0) {
            return R.error("详情数据不能为空");
        }

        String loginUserId = ShiroUtils.getUserId();
        TsUserChange tsUserChange = new TsUserChange().setUserId(loginUserId).setStatus(1).queryFirst();

        tcwPaymentReturn.setStatus(0);
        tcwPaymentReturn.setCreateChangeId(String.valueOf(tsUserChange.getId()));
        tcwPaymentReturn.setEffectStock(FlowEnum.EffectStock.NOT_EFFECT.value);
        tcwPaymentReturn.setAnnexFile("0个附件");
        tcwPaymentReturnMapper.insert(tcwPaymentReturn);


        Long operateCompanyPrepaymentId = null;
        //是否重复
        Map<String, Object> extraParam = new HashMap<String, Object>();
        for (int i = 0; i < detailJA.size(); i++) {
            JSONObject detailJO = detailJA.getJSONObject(i);
            TcwPaymentReturnItem tcwPaymentReturnItem = JSON.parseObject(JSON.toJSONString(detailJO), TcwPaymentReturnItem.class);
            tcwPaymentReturnItem.setPaymentReturnBid(tcwPaymentReturn.getBid());
            tcwPaymentReturnItem.setStatus(0);
            if(detailJO.get("vgsjc") == null){
                throw new RuntimeException("运营公司简称不能为空,不允许保存!");
            }
            if(detailJO.get("vyhzhmc") == null){
                throw new RuntimeException("银行账户名称不能为空,不允许保存!");
            }
            if(detailJO.get("thAmount") == null || detailJO.get("thAmount").equals("")){
                throw new RuntimeException("退回金额不能为空,不允许保存!");
            }
            if (extraParam.get(detailJO.get("vgsbm").toString()) != null){
                throw new RuntimeException("运营公司编码不能重复,不允许保存!");
            }
            if (tcwPaymentReturnItem.getThAmount().compareTo(new BigDecimal(0)) <= 0){
                throw new RuntimeException("退回金额小于等于0,不允许保存!");
            }
            if (tcwPaymentReturn.getPaymentReturnType() == TcwPaymentReturnEnum.PaymentReturnType.TPHK.value){
                //保存时判定有对公打款金额优先
                if (new TcwOperateCompanyPrepayment().setVgsbm(detailJO.get("vgsbm").toString()).setOperateCompanyPrepaymentType(0).setFkVyhzh(detailJO.get("vyhzh").toString()).where("A.PreResAmount != 0").count() != 0){
                    throw new RuntimeException(detailJO.get("vgsjc")+"还有对公打款额度，请选择对公打款重新进行操作!");
                }
                if (tcwPaymentReturnItem.getAccountType() == null || tcwPaymentReturnItem.getAccountType() == 0){
                    throw new RuntimeException("账号类型不能为空,不允许保存!");
                }
                //店铺回款只允许收款账户这个未审核只有一条
                if (new TcwPaymentReturnItem()
                        .addLeftJoin("TCW_PaymentReturn B ON B.Bid = A.PaymentReturnBid")
                        .where("B.EffectStock != 2 ")
                        .setCompanyBankId(tcwPaymentReturnItem.getCompanyBankId()).setStatus(0).count() != 0){
                    throw new RuntimeException(detailJO.get("vgsjc") + "预付款退回申请已存在一条未审核数据,请核实再操作!");
                }
            }else {
                //判断是否有提款账号
                if(detailJO.get("tkVid") == null){
                    throw new RuntimeException("提款账户编码不能为空,不允许保存!");
                }
                //退回金额不允许超出可退额度
                if (tcwPaymentReturnItem.getThAmount().compareTo(tcwPaymentReturnItem.getRefundableAmount()) == 1){
                    throw new RuntimeException("退回金额不允许超出可退额度,不允许保存!");
                }
                //只允许这个运营预付款未审核只有一条
                if (new TcwPaymentReturnItem().setOperateCompanyPrepaymentId(tcwPaymentReturnItem.getOperateCompanyPrepaymentId()).setStatus(0).count() != 0){
                    throw new RuntimeException(detailJO.get("vgsjc") + "预付款退回申请已存在一条未审核数据,请核实再操作!");
                }
            }
            if(tcwPaymentReturnItem.getOperateCompanyPrepaymentId()!=null) operateCompanyPrepaymentId = tcwPaymentReturnItem.getOperateCompanyPrepaymentId();
            extraParam.put(detailJO.get("vgsbm").toString(),1);
            tcwPaymentReturnItemMapper.insert(tcwPaymentReturnItem);
        }
        String companyName = "";
        if(tcwPaymentReturn.getPaymentReturnType() == 0){//店铺回款
            TbStaticConfig tbStaticConfig = new TbStaticConfig().setKeyOne("YS_ProcInstOther").setKeyTwo("YS_ProcInstOther-TCW_PaymentReturn").queryFirst();
            if(tbStaticConfig!=null) companyName = tbStaticConfig.getName();
        }else{//对公打款
            TcwOperateCompanyPrepayment tcwOperateCompanyPrepayment = new TcwOperateCompanyPrepayment().setId(operateCompanyPrepaymentId).queryFirst();
            if(tcwOperateCompanyPrepayment!=null) companyName = tcwOperateCompanyPrepayment.getVyhzhmc();
        }

        YsMenu ysMenu = new YsMenu().setId(MenuId.TCW_PaymentReturn).queryFirst();
        if (ysMenu.getFlowModelId().longValue() != 0L) {
            YspModel yspModel = new YspModel().setId(ysMenu.getFlowModelId()).queryFirst();
            String codeModel = yspModel.getCode();
            String createUserId = ShiroUtils.getUserId();
            yspTaskService.init(codeModel, tcwPaymentReturn.getBid(), createUserId);
            yspTaskService.setOtherParams(tcwPaymentReturn.getBid(),null,companyName);
        }

        return R.ok(AddDto.gotoEdit("/web/finance/tcwPaymentReturn/toEdit?bid=" + tcwPaymentReturn.getBid()));
    }


    /**
     * 修改预付款退回申请
     * @param params
     * @param subData
     * @return
     * @throws Exception
     */
    @Override
    @Transactional(timeout=120,propagation= Propagation.REQUIRES_NEW)
    public R edit(Map<String, Object> params, String subData) throws Exception {
        //验证
        String msg = yzMsg(params);
        if (msg != null){
            return R.error(msg);
        }
        TcwPaymentReturn tcwPaymentReturn = JSON.parseObject(JSON.toJSONString(params), TcwPaymentReturn.class);
        if (new TcwPaymentReturn().setBid(tcwPaymentReturn.getBid()).where("A.id != " + tcwPaymentReturn.getId()).count() != 0){
            return R.error("该单号已存在，核实后再操作!");
        }
        // 验证是否有详情数据
        JSONArray detailJA = JSON.parseArray(subData);
        if (detailJA == null || detailJA.size() == 0) {
            return R.error("详情数据不能为空");
        }

        //判断是否实在制单中
        Integer flowState = yspTaskService.flowState(tcwPaymentReturn.getBid());

        if (flowState != 0){
            return R.error("预付款退回申请单不是制单中,不允许保存!");
        }

        tcwPaymentReturnMapper.update(tcwPaymentReturn);

        diySqlMapper.deleteTcwPaymentReturnBid(tcwPaymentReturn.getBid());

        Long operateCompanyPrepaymentId = null;
        //是否重复
        Map<String, Object> extraParam = new HashMap<String, Object>();
        for (int i = 0; i < detailJA.size(); i++) {
            JSONObject detailJO = detailJA.getJSONObject(i);
            TcwPaymentReturnItem tcwPaymentReturnItem = JSON.parseObject(JSON.toJSONString(detailJO), TcwPaymentReturnItem.class);
            tcwPaymentReturnItem.setPaymentReturnBid(tcwPaymentReturn.getBid());
            if(detailJO.get("vgsjc") == null){
                throw new RuntimeException("运营公司简称不能为空,不允许保存!");
            }
            if(detailJO.get("vyhzhmc") == null){
                throw new RuntimeException("银行账户名称不能为空,不允许保存!");
            }
            if(detailJO.get("thAmount") == null || detailJO.get("thAmount").equals("")){
                throw new RuntimeException("退回金额不能为空,不允许保存!");
            }
            if (extraParam.get(detailJO.get("vgsbm").toString()) != null){
                throw new RuntimeException("运营公司编码不能重复,不允许保存!");
            }
            if (tcwPaymentReturnItem.getThAmount().compareTo(new BigDecimal(0)) <= 0){
                throw new RuntimeException("退回金额小于等于0,不允许保存!");
            }
            if (tcwPaymentReturn.getPaymentReturnType() == TcwPaymentReturnEnum.PaymentReturnType.TPHK.value){
                //保存时判定有对公打款金额优先
                if (new TcwOperateCompanyPrepayment().setVgsbm(detailJO.get("vgsbm").toString()).setFkVyhzh(detailJO.get("vyhzh").toString()).where("A.PreResAmount != 0").count() != 0){
                    throw new RuntimeException(detailJO.get("vgsjc")+"还有对公打款额度，请选择对公打款重新进行操作!");
                }
                if (tcwPaymentReturnItem.getAccountType() == null || tcwPaymentReturnItem.getAccountType() == 0){
                    throw new RuntimeException("账号类型不能为空,不允许保存!");
                }
            }else {
                //判断是否有提款账号
                if(detailJO.get("tkVid") == null){
                    throw new RuntimeException("提款账户编码不能为空,不允许保存!");
                }
                //退回金额不允许超出可退额度
                if (tcwPaymentReturnItem.getThAmount().compareTo(tcwPaymentReturnItem.getRefundableAmount()) == 1){
                    throw new RuntimeException("退回金额不允许超出可退额度,不允许保存!");
                }
                //只允许这个运营预付款未审核只有一条
                if (new TcwPaymentReturnItem().setOperateCompanyPrepaymentId(tcwPaymentReturnItem.getOperateCompanyPrepaymentId()).setStatus(0).count() != 0){
                    throw new RuntimeException(detailJO.get("vgsjc") + "预付款退回申请已存在一条未审核数据,请核实再操作!");
                }
            }
            if(tcwPaymentReturnItem.getOperateCompanyPrepaymentId()!=null) operateCompanyPrepaymentId = tcwPaymentReturnItem.getOperateCompanyPrepaymentId();
            extraParam.put(detailJO.get("vgsbm").toString(),1);
            tcwPaymentReturnItemMapper.insert(tcwPaymentReturnItem);
        }

        String companyName = "";
        if(tcwPaymentReturn.getPaymentReturnType() == 0){//店铺回款
            TbStaticConfig tbStaticConfig = new TbStaticConfig().setKeyOne("YS_ProcInstOther").setKeyTwo("YS_ProcInstOther-TCW_PaymentReturn").queryFirst();
            if(tbStaticConfig!=null) companyName = tbStaticConfig.getName();
        }else{//对公打款
            TcwOperateCompanyPrepayment tcwOperateCompanyPrepayment = new TcwOperateCompanyPrepayment().setId(operateCompanyPrepaymentId).queryFirst();
            if(tcwOperateCompanyPrepayment!=null) companyName = tcwOperateCompanyPrepayment.getVyhzhmc();
        }
        yspTaskService.setOtherParams(tcwPaymentReturn.getBid(),null,companyName);

        return R.ok(AddDto.gotoEdit("/web/finance/tcwPaymentReturn/toEdit?bid=" + tcwPaymentReturn.getBid()));
    }

    /**
     * 预付款退回申请流转
     * @param id
     * @return
     * @throws Exception
     */
    @Override
    @Transactional(timeout=120,propagation= Propagation.REQUIRES_NEW)
    public R flowPass(Long id, String loginUserId) throws Exception {
        TcwPaymentReturn entity = new TcwPaymentReturn().setId(id).queryFirst();
        String bid = entity.getBid();
        try {
            YsProcInst ysProcInst = new YsProcInst().setBid(bid).queryFirst();
            TcwAccountCountForCompany account = null;
            List<TcwPaymentReturnItem> tcwPaymentReturnItemList = null;
            // 若流程是初始化状态，需要验证账户金额
            if (ysProcInst.getStateFlow() == YsProcInstEnum.StateFlow.INIT.value) {
                //查询子件
                tcwPaymentReturnItemList = new TcwPaymentReturnItem().setPaymentReturnBid(bid).queryList();
                for (TcwPaymentReturnItem tcwPaymentReturnItem : tcwPaymentReturnItemList){
                    //查询运营公司银行账户
                    ThrOperateCompanyBankInfo thrOperateCompanyBankInfo  = new ThrOperateCompanyBankInfo().setId(tcwPaymentReturnItem.getCompanyBankId()).queryFirst();
                    //获取公司编码
                    String vGsBm = thrOperateCompanyBankInfo.getVgsbm();
                    //根据公司编码获取对应的实时资金表信息
                    account = new TcwAccountCountForCompany().setVGsBm(vGsBm).queryFirst();
                    //获取对应的实时资金信息
                    BigDecimal amountAble = account.getFJe().add(account.getFFzEd()).subtract(account.getFDjJe());
                    //判断金额是否大于公司的实时资金
                    if (amountAble.compareTo(tcwPaymentReturnItem.getThAmount()) < 0) {
                        return R.error("【" + vGsBm + "】账户可用余额不足，无法流转");
                    }
                }

            }

            Flow f = yspTaskService.flowPass(bid, loginUserId);
            if (f.getCode() == Flow.Code.FAILED.value) {
                return R.error(f.getMsg());
            } else {
                // 若流程是初始化状态，冻结金额
                if (ysProcInst.getStateFlow() == YsProcInstEnum.StateFlow.INIT.value) {
                    for (TcwPaymentReturnItem tcwPaymentReturnItem : tcwPaymentReturnItemList) {
                        //查询运营公司银行账户
                        ThrOperateCompanyBankInfo thrOperateCompanyBankInfo  = new ThrOperateCompanyBankInfo().setId(tcwPaymentReturnItem.getCompanyBankId()).queryFirst();
                        //获取公司编码
                        String vGsBm = thrOperateCompanyBankInfo.getVgsbm();
                        //根据公司编码获取对应的实时资金表信息
                        account = new TcwAccountCountForCompany().setVGsBm(vGsBm).queryFirst();
                        account.setFDjJe(account.getFDjJe().add(tcwPaymentReturnItem.getThAmount()));
                        tcwAccountCountForCompanyMapper.update(account);

                        tcwOperateFrozenRunningMapper.insert(new TcwOperateFrozenRunning().setSourceId(tcwPaymentReturnItem.getId())
                                .setChangeFdjje(tcwPaymentReturnItem.getThAmount())
                                .setFdjje(account.getFDjJe())
                                .setVgsbm(vGsBm)
                                .setSourceType(TcwOperateFrozenRunningEnum.DocumentType.TCWPAYMENTRETURNITEM.value)
                                .setRemark("预付款退回流转,账户资金:"+account.getFJe()+",负债额度:"+account.getFFzEd())
                        );
                    }
                }
                if (f.getState() == Flow.State.FINISH.value) {
                    R r = flowFinish(entity);
                    if (r.getCode() == 1) {
                        return R.error(r.getMsg());
                    }
                }
                return R.ok();
            }
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException(e.getMessage());
        }
    }

    /**
     * 预付款退回申请退回
     * @param id
     * @return
     * @throws Exception
     */
    @Override
    @Transactional(timeout=120,propagation= Propagation.REQUIRES_NEW)
    public R flowRefuse(Long id,String reason, String loginUserId) throws Exception {
        TcwPaymentReturn entity = new TcwPaymentReturn().setId(id).queryFirst();
        String bid = entity.getBid();
        try {
            R r = yspTaskService.flowRefuse(bid, reason, loginUserId);

            if (r.getCode() == R.Code.SUCCESS.value) {
                YsProcInst ysProcInst = new YsProcInst().setBid(bid).queryFirst();
                // 若退回到制单状态，则解冻账户
                if (ysProcInst.getStateFlow() == YsProcInstEnum.StateFlow.INIT.value) {
                    List<TcwPaymentReturnItem> tcwPaymentReturnItemList = new TcwPaymentReturnItem().setPaymentReturnBid(bid).queryList();
                    for (TcwPaymentReturnItem tcwPaymentReturnItem : tcwPaymentReturnItemList){
                        //查询运营公司银行账户
                        ThrOperateCompanyBankInfo thrOperateCompanyBankInfo  = new ThrOperateCompanyBankInfo().setId(tcwPaymentReturnItem.getCompanyBankId()).queryFirst();
                        //获取公司编码
                        String vGsBm = thrOperateCompanyBankInfo.getVgsbm();
                        //根据公司编码获取对应的实时资金表信息
                        TcwAccountCountForCompany account = new TcwAccountCountForCompany().setVGsBm(vGsBm).queryFirst();
                        account.setFDjJe(account.getFDjJe().subtract(tcwPaymentReturnItem.getThAmount()));
                        tcwAccountCountForCompanyMapper.update(account);

                        tcwOperateFrozenRunningMapper.insert(new TcwOperateFrozenRunning().setSourceId(tcwPaymentReturnItem.getId())
                                .setChangeFdjje(tcwPaymentReturnItem.getThAmount())
                                .setFdjje(account.getFDjJe())
                                .setVgsbm(vGsBm)
                                .setSourceType(TcwOperateFrozenRunningEnum.DocumentType.TCWPAYMENTRETURNITEM.value)
                                .setRemark("预付款退回退回,账户资金:"+account.getFJe()+",负债额度:"+account.getFFzEd()));
                    }
                }
            }
            return r;
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException("预付款退回申请退回失败!");
        }
    }

    /**
     * 预付款退回申请驳回
     * @param id
     * @return
     * @throws Exception
     */
    @Override
    @Transactional(timeout=120,propagation= Propagation.REQUIRES_NEW)
    public R flowInit(Long id,String reason, String loginUserId) throws Exception {
        TcwPaymentReturn entity = new TcwPaymentReturn().setId(id).queryFirst();
        String bid = entity.getBid();
        try {
            R r = yspTaskService.flowInit(bid, reason, loginUserId);

            if (r.getCode() == R.Code.SUCCESS.value) {
                YsProcInst ysProcInst = new YsProcInst().setBid(bid).queryFirst();
                // 若退回到制单状态，则解冻账户
                if (ysProcInst.getStateFlow() == YsProcInstEnum.StateFlow.INIT.value) {
                    List<TcwPaymentReturnItem> tcwPaymentReturnItemList = new TcwPaymentReturnItem().setPaymentReturnBid(bid).queryList();
                    for (TcwPaymentReturnItem tcwPaymentReturnItem : tcwPaymentReturnItemList){
                        //查询运营公司银行账户
                        ThrOperateCompanyBankInfo thrOperateCompanyBankInfo  = new ThrOperateCompanyBankInfo().setId(tcwPaymentReturnItem.getCompanyBankId()).queryFirst();
                        //获取公司编码
                        String vGsBm = thrOperateCompanyBankInfo.getVgsbm();
                        //根据公司编码获取对应的实时资金表信息
                        TcwAccountCountForCompany account = new TcwAccountCountForCompany().setVGsBm(vGsBm).queryFirst();
                        account.setFDjJe(account.getFDjJe().subtract(tcwPaymentReturnItem.getThAmount()));
                        tcwAccountCountForCompanyMapper.update(account);

                        tcwOperateFrozenRunningMapper.insert(new TcwOperateFrozenRunning().setSourceId(tcwPaymentReturnItem.getId())
                                .setChangeFdjje(tcwPaymentReturnItem.getThAmount())
                                .setFdjje(account.getFDjJe())
                                .setVgsbm(vGsBm)
                                .setSourceType(TcwOperateFrozenRunningEnum.DocumentType.TCWPAYMENTRETURNITEM.value)
                                .setRemark("预付款退回驳回,账户资金:"+account.getFJe()+",负债额度:"+account.getFFzEd()));
                    }
                }
            }
            return r;
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException("预付款退回申请流转失败!");
        }
    }

    /**
     * 删除预付款退回申请
     * @param id 主键id
     * @return
     * @throws Exception
     */
    @Override
    @Transactional(timeout=120,propagation= Propagation.REQUIRES_NEW)
    public R del(Long id) throws Exception {
        TcwPaymentReturn tcwPaymentReturn = new TcwPaymentReturn().setId(id).queryFirst();
        if (tcwPaymentReturn == null){
            throw new RuntimeException("预付款退回申请单据不存在,请核实后再操作!");
        }

        //判断是否实在制单中
        Integer flowState = yspTaskService.flowState(tcwPaymentReturn.getBid());

        if (flowState != 0){
            throw new RuntimeException("预付款退回申请单不是制单中,不允许删除!");
        }
        yspTaskService.flowDelete(tcwPaymentReturn.getBid(),tcwPaymentReturn.getCreateChangeId());

        tcwPaymentReturnMapper.deleteTrue(id);

        diySqlMapper.deleteTcwPaymentReturnBid(tcwPaymentReturn.getBid());

        return R.ok("删除成功!");
    }



    private String yzMsg(Map<String, Object> infoMap){
        //验证导入字段
        String backMsg = "";
        //获取pc字段数据
        List<YsCol> listField = new YsCol()
                .where("A.MenuId = "+ MenuId.TCW_PaymentReturn)
                .setOrderby("A.SortNo ASC")
                .queryList();
        //验证必填字段的非空；其他字段的长度限制、类型
        try {
            backMsg = checkUtil.checkTableColLengthAndDataType(
                    "TCW_PaymentReturn",
                    listField,
                    infoMap,
                    ysColItem->ysColItem.getFormEditRequired()!=null && ysColItem.getFormEditRequired() == 1
            );
            if(backMsg!=null && !"".equals(backMsg)){//若有误，则跳过这条信息
                return backMsg;
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    @Transactional
    public R flowFinish(TcwPaymentReturn entity) throws Exception {
        entity.setEffectStock(1);
        tcwPaymentReturnMapper.update(entity);

        // 同名对公户
        if (entity.getPaymentReturnType() == TcwPaymentReturnEnum.PaymentReturnType.DGDK.value){
            List<TcwPaymentReturnItem> tcwPaymentReturnItemList = new TcwPaymentReturnItem().setPaymentReturnBid(entity.getBid()).queryList();
            for (TcwPaymentReturnItem tcwPaymentReturnItem : tcwPaymentReturnItemList) {
                //查询运营公司银行账户
                ThrOperateCompanyBankInfo thrOperateCompanyBankInfo  = new ThrOperateCompanyBankInfo().setId(tcwPaymentReturnItem.getCompanyBankId()).queryFirst();
                //获取公司编码
                String vGsBm = thrOperateCompanyBankInfo.getVgsbm();
                //根据公司编码获取对应的实时资金表信息
                TcwAccountCountForCompany account = new TcwAccountCountForCompany().setVGsBm(vGsBm).queryFirst();
                account.setFDjJe(account.getFDjJe().subtract(tcwPaymentReturnItem.getThAmount()));
                tcwAccountCountForCompanyMapper.update(account);

                tcwOperateFrozenRunningMapper.insert(new TcwOperateFrozenRunning().setSourceId(tcwPaymentReturnItem.getId())
                        .setChangeFdjje(tcwPaymentReturnItem.getThAmount())
                        .setFdjje(account.getFDjJe())
                        .setVgsbm(vGsBm)
                        .setSourceType(TcwOperateFrozenRunningEnum.DocumentType.TCWPAYMENTRETURNITEM.value)
                        .setRemark("预付款流转成功(同名对公账户),账户资金:"+account.getFJe()+",负债额度:"+account.getFFzEd())
                );

                //判断扣减运营预付款的金额
                TcwOperateCompanyPrepayment tcwOperateCompanyPrepayment = new TcwOperateCompanyPrepayment().setId(tcwPaymentReturnItem.getOperateCompanyPrepaymentId()).queryFirst();
                if (tcwOperateCompanyPrepayment.getPreResAmount().compareTo(tcwPaymentReturnItem.getThAmount()) == -1){
                    throw new RuntimeException("运营预付款剩余金额不足,流转失败!");
                }
                tcwOperateCompanyPrepayment.setPreReturnAmount(tcwOperateCompanyPrepayment.getPreReturnAmount().add(tcwPaymentReturnItem.getThAmount()));
                tcwOperateCompanyPrepayment.setPreResAmount(tcwOperateCompanyPrepayment.getPreResAmount().subtract(tcwPaymentReturnItem.getThAmount()));
                tcwOperateCompanyPrepaymentMapper.update(tcwOperateCompanyPrepayment);

                //更改支付成功
                tcwPaymentReturnItem.setStatus(2);
                tcwPaymentReturnItemMapper.update(tcwPaymentReturnItem);

                //查询对应收款账户的id
                TbCompanyBankInfo tbCompanyBankInfo = new TbCompanyBankInfo().setVid(tcwOperateCompanyPrepayment.getVid()).queryFirst();

                /**
                 * 新增一条流水
                 * 必填：vgsbm划出公司编码；vgsbmp划入公司编码；vjylx交易类型；fje交易金额；djysj交易时间；dshsj审核时间；vbz备注
                 * 选填：mname;mtype;mnid;mbid;mguid；writeTime记账时间（如果为空，默认审核时间）
                 */
                R r = tcwAccountDetailedForCompanyService.addTcwAccountDetailedForCompanyWithJc(
                        account.getVGsBm(), account.getVGsJc(), thrOperateCompanyBankInfo.getVyhzh(), thrOperateCompanyBankInfo.getVyhzhmc(),
                        TransactionTypeEnum.FinanceType.TCW_PaymentReturn.name, tcwPaymentReturnItem.getThAmount().negate(), entity.getCreateTime(), new Date(),
                        "预付款退回申请：单号" + entity.getBid(),entity.getBid(),
                        null);
                if(r.getCode().equals(R.Code.FAILED.value)){//失败
                    logger.info("新增业务交易流水失败:"+r.getMsg());
                    throw new RuntimeException(r.getMsg());
                }

                TbBaseInfo tcwFinancialTransactionTypeItem = tcwFinancialTransactionFlowService.getTransactionType(TransactionTypeEnum.FinanceType.TCW_PaymentReturn.name);
                        //new TcwFinancialTransactionTypeItem().setVremark(TransactionTypeEnum.FinanceType.TCW_PaymentReturn.name).queryFirst();
                if (tcwFinancialTransactionTypeItem == null){
                    logger.info("财务交易类型表("+TransactionTypeEnum.FinanceType.TCW_PaymentReturn.name+")不存在");
                    throw new RuntimeException("财务交易类型表("+TransactionTypeEnum.FinanceType.TCW_PaymentReturn.name+")不存在");
                }

                //新增财务流水
                R res2 = tcwFinancialTransactionFlowService.add(true, tbCompanyBankInfo.getId(), tcwFinancialTransactionTypeItem.getBid(),
                        thrOperateCompanyBankInfo.getVyhzhmc(), thrOperateCompanyBankInfo.getVkhh(), thrOperateCompanyBankInfo.getVyhzh(), tcwPaymentReturnItem.getThAmount().negate(),
                        entity.getCreateTime(), entity.getUpdateTime(), entity.getUpdateTime(), "预付款退回申请：单号" + entity.getBid(),
                        2, entity.getId());

                if(res2.getCode().equals(R.Code.FAILED.value)){//失败
                    logger.info("新增财务流水失败:"+res2.getMsg());
                    throw new RuntimeException(res2.getMsg());
                }
            }
        }
        return R.ok();
    }

    @Override
    public R cancel(String bid,Long id) {
        if (bid == null || bid.length() == 0) {
            return R.error("ID不能为空!");
        }

        TcwPaymentReturn entity = new TcwPaymentReturn().setBid(bid).queryFirst();
        if (entity.getEffectStock() != FlowEnum.EffectStock.EFFECTED.value) {
            return R.error("未生效数据无法作废!");
        }
        if (entity.getPaymentReturnType() == TcwPaymentReturnEnum.PaymentReturnType.DGDK.value){
            return R.error("对公打款不允许作废!");
        }
        List<TcwPaymentReturnItem> tcwPaymentReturnItemList = new TcwPaymentReturnItem().setPaymentReturnBid(bid).queryList();
        for (TcwPaymentReturnItem tcwPaymentReturnItem : tcwPaymentReturnItemList){
            //是否被外币付款单使用
            int count = new TcwWanliPaymentReturnItem().setPaymentReturnItemId(tcwPaymentReturnItem.getId())
                    .count();
            if (count != 0){
                return R.error("该数据已经被万里汇预付款退回使用,无法作废!");
            }
            //查询运营公司银行账户
            ThrOperateCompanyBankInfo thrOperateCompanyBankInfo  = new ThrOperateCompanyBankInfo().setId(tcwPaymentReturnItem.getCompanyBankId()).queryFirst();
            //获取公司编码
            String vGsBm = thrOperateCompanyBankInfo.getVgsbm();
            //根据公司编码获取对应的实时资金表信息
            TcwAccountCountForCompany account = new TcwAccountCountForCompany().setVGsBm(vGsBm).queryFirst();
            account.setFDjJe(account.getFDjJe().subtract(tcwPaymentReturnItem.getThAmount()));
            tcwAccountCountForCompanyMapper.update(account);

            tcwOperateFrozenRunningMapper.insert(new TcwOperateFrozenRunning().setSourceId(tcwPaymentReturnItem.getId())
                    .setChangeFdjje(tcwPaymentReturnItem.getThAmount())
                    .setFdjje(account.getFDjJe())
                    .setVgsbm(vGsBm)
                    .setSourceType(TcwOperateFrozenRunningEnum.DocumentType.TCWPAYMENTRETURNITEM.value)
                    .setRemark("预付款退回作废,账户资金:"+account.getFJe()+",负债额度:"+account.getFFzEd()));
        }

        // 作废主数据
        entity.setEffectStock(FlowEnum.EffectStock.CANCELD.value);
        tcwPaymentReturnMapper.update(entity);
        return R.ok();
    }


    //获取列表数据
    @Override
    @Transactional
    public Map<String,Object> getExtraParam( String bid) throws Exception{

        Map entity = new TcwPaymentReturn().setBid(bid)
                .addLeftJoin("YS_ProcInst Ysp ON Ysp.bid = A.bid")//流程表
                .addField("FORMAT(Ysp.UpdateTime, 'yyyy-MM-dd hh:mm:ss') AS updateTime1")//审核时间
                .queryFirstMap();
        entity.remove("createTime");
        return entity;
    }
    //获取子列表数据
    @Override
    @Transactional
    public List<Map<String, Object>> getItemList( String bid) throws Exception{
        List<Map<String, Object>> sonlist = new TcwPaymentReturnItem()
                .addLeftJoin("THR_OperateCompanyBankInfo ocbi ON ocbi.id = A.companyBankId")//银行账户
                .addField("ocbi.vyhzhmc AS vyhzhmc,ocbi.vkhh AS vkhh,ocbi.vyhzh AS vyhzh,ocbi.vlhh AS vlhh")
                .addLeftJoin("THR_OperateCompanyApply toc ON toc.vgsbm = ocbi.vgsbm")//运营公司
                .addField("toc.vgsjc AS vgsjc,toc.vgsbm AS vgsbm")
                .addLeftJoin("TCW_OperateCompanyPrepayment tocp ON  tocp.id = A.operateCompanyPrepaymentId ")
                .addField("tocp.Vid AS tkVid,tocp.Vyhzh AS tkVyhzh,tocp.Vkhh AS tkVkhh,tocp.Vyhzhmc AS tkVyhzhmc,tocp.preResAmount AS refundableAmount,tocp.id AS operateCompanyPrepaymentId")

                .addLeftJoin("TB_StaticConfig D ON D.Lev=toc.OperationsAttribute AND D.KeyTwo = 'OperateCompanyApply-OperationsAttribute' ")
                .addField("D.NameSub operationsAttributeTxt")

                .setPaymentReturnBid(bid)
                .queryMap();
        return sonlist;
    }

}
